home *** CD-ROM | disk | FTP | other *** search
/ C/C++ Interactive Reference Guide / C-C++ Interactive Reference Guide.iso / c_ref / csource4 / 203_01 / yam3.c < prev    next >
Text File  |  1979-12-31  |  13KB  |  681 lines

  1. /*
  2. $title ('yam3.c: terminal mode utilities')
  3. $date (9 nov 85)
  4. */
  5.  
  6. #include "yam.h"
  7. #define BRKKEY STX
  8.  
  9. int overrun;    /* true if data is lost */
  10.  
  11. /****************************************************************************
  12. FUNCTION:
  13.     two-way conversation with remote -whatever.
  14.     Printer is buffered such that it needn't be as fast as the baudrate
  15.     as long as it eventually gets a chance to catch up.
  16.     This buffering also allows one to write the received data out to disk
  17.     after the conservation has started.
  18.  
  19. CALLING PARAMETERS:
  20.     none.
  21. ===========================================================================*/
  22. term()
  23. {
  24.     register c, cc;
  25.     unsigned charsent;
  26.  
  27.     sayterm();
  28.     charsent = 0;
  29.         /* reset tab stop */
  30.     Ttycol = 0;
  31.         /* data flow flags */
  32.     Waitecho=Txwait=overrun=FALSE;
  33.  
  34. #ifdef IBMPC
  35.         /* enbable terminal mode */
  36.     enblcm(TRUE);
  37. #endif
  38.  
  39.     while(1)
  40.     {
  41.  
  42. /* IBMPC implementation uses assembly language interrupt routine for modem
  43.    input.  Because the IBM terminal I/O is so painfully slow, interrupts were
  44.    added to avoid loosing characters and allow operation at >300 baud.*/
  45. #ifndef IBMPC
  46.             /**** modem in ****/
  47.         if (MIREADY)
  48.         {
  49.             *bufcq = MICHAR;
  50.             if (!Ignrx)
  51.                 bufcq++;
  52.             else
  53.                 if(!index(*bufcq, rxnono))
  54.                     bufcq++;
  55.             Timeout=0;
  56.             if(bufcq >= bufend)
  57.             {
  58.                 Wrapped=TRUE;
  59.                 bufcq=bufst;
  60.             }
  61.  
  62.             if(--Nfree == LOWWATER)
  63.                 MOCHAR(Xoffflg=TRUE);
  64.             else if(Nfree==0)
  65.                 overrun = TRUE;
  66.             continue;
  67.         }
  68. #endif
  69.             /**** keyboard ****/
  70.         if(CIREADY)
  71.         {
  72.             cfast = CICHAR;
  73.             if (doykbd(cfast))
  74.                 return;
  75.             continue;
  76.         }
  77.  
  78.             /**** console out ****/
  79.         if(bufcdq != bufcq)
  80.         if (COREADY)
  81.         {
  82.             switch(cfast = (*bufcdq & 0x7F) )
  83.             {
  84.             case '\b':
  85.                  if(Ttycol)
  86.                     --Ttycol;
  87.                 break;
  88.             case '\t':
  89.                 CONOUT(' ');
  90.                 if (++Ttycol % tabstop)
  91.                     continue;
  92.                 else
  93.                     goto chuckit;
  94.             case '\r':
  95.                 Ttycol=0;
  96.                 break;
  97.             case '\n':
  98.                     /* continue transmit if enabled */
  99.                 if(Txeoln==EOL_CRWAIT)
  100.                     Waitecho=FALSE;
  101.                 Ttycol=0;
  102.                 break;
  103. #ifdef XMODEM
  104.             case CPMEOF:
  105.                 pstat("");
  106.                 return;
  107.                 /* bell */
  108.             case 007:
  109.                 break;
  110. #endif
  111.             default:
  112.                 if (cfast==xoff)
  113.                 {
  114. #ifdef STATLINE
  115.                     sayterm();
  116. #endif
  117.                     Txgo=FALSE;
  118.                     goto chuckit;
  119.                 }
  120.                 else if (cfast==xon)
  121.                 {
  122.                     Txgo=TRUE;
  123. #ifdef STATLINE
  124.                     sayterm();
  125. #endif
  126.                     goto chuckit;
  127.                 }
  128.  
  129.                 else if(Ctlview)
  130.                 {
  131.                         /* preceed with ~ if parity bit set */
  132.                     if (cfast & 0x80)
  133.                     {
  134.                         CONOUT('~');
  135.                         ++Ttycol;
  136.                     }
  137.                         /* view control characters */
  138.                     if (cfast < ' ')
  139.                     {
  140.                         CONOUT('^');
  141.                         CONOUT(cfast|0x40);
  142.                         Ttycol += 2;
  143.                         goto chuckit;
  144.                     }
  145.                 } /* ctlview */
  146.                 else
  147.                     ++Ttycol;
  148.             } /* switch */
  149.  
  150.                 /* resume file sending if waiting for go char */
  151.             if (cfast==GOchar && Txeoln==EOL_CRPROMPT)
  152.                 Waitecho=FALSE;
  153.  
  154.             CONOUT(cfast);
  155.  
  156.             if(Echo)
  157.             {
  158.                 sendbyte(cfast);
  159.                 if(Chat && cfast== '\r')
  160.                 {
  161.                     CONOUT('\n');
  162. #ifndef XMODEM
  163.                     sendbyte('\n');
  164. #endif
  165.                 }
  166.             } /* echo */
  167. chuckit:
  168.                 /* if not receiving, buffer need not
  169.                    be dumped.  bump up number of free space left */
  170.                 /* Some systems echo data sent(as in editor). 
  171.                    If receiving an echo term would emit dc3
  172.                    when the buffer fills up. This will prevent that too */
  173.             if (!Rfile)
  174.                 Nfree++;
  175.  
  176.             if(++bufcdq >= bufend)
  177.                 bufcdq=bufst;
  178.             continue;
  179.         }
  180.  
  181.             /**** printer ****/
  182.         if (Pflag && (bufpcdq!=bufcq) && LPREADY)
  183.         {
  184.             LPOUT(*bufpcdq++ & 0177);
  185.             if (bufpcdq >= bufend)
  186.                 bufpcdq=bufst;
  187.         }
  188.  
  189.             /**** modem out ****/
  190.         if(MOREADY)
  191.         {
  192.                 /* if transmit file is open(Tfile) and we are not waiting
  193.                    for throttle(Txwait) and not waiting for an echo(!Waitecho)
  194.                    and transmission is not suspended by xoff(Txgo) send char. */
  195.             if(Tfile && !Txwait && !Waitecho && Txgo)
  196.             {
  197.                     /* get char from file */
  198.                 c = getc(fin);
  199.                 if(c==EOF)
  200.                 {
  201.                     closetx(FALSE);
  202. #ifdef XMODEM
  203.                     pstat("");
  204.                     return;
  205. #else
  206.                         /* return to command mode on EOF if true */
  207.                     if(Exoneof)
  208.                         return;
  209.  
  210.                         /* explain were in term mode now */
  211.                     sayterm();
  212. #endif
  213.                 }
  214.  
  215.                     /* wait for echoes to stop after waitnum characters.
  216.                        Waitbunch set by 'et', Waitnum by 'pwn' */
  217.                 if(Waitbunch && ++charsent==Waitnum)
  218.                 {
  219.                     charsent=0;
  220.                         /* cause wait for echo */
  221.                     if(Waitnum>1)
  222.                     {
  223.                         Waitecho=TRUE;
  224.                         Timeout=0;
  225.                     }
  226.                         /* reset throttle wait parms */
  227.                     else
  228.                     {
  229.                         Txwait=TRUE;
  230.                         Txtimeout=Throttle;
  231.                     }
  232.                 }
  233.                     /* end of line processing */
  234.                 if(c=='\r')
  235.                 {
  236.                     switch(Txeoln)
  237.                     {
  238.                     case EOL_NL:
  239.                         continue;
  240.                     case EOL_CRPROMPT:
  241.                     case EOL_CRWAIT:
  242.                         Waitecho=TRUE;
  243.                         Timeout=0;
  244.                     case EOL_CR:
  245.                         if(Tfile)
  246.                         {
  247.                             if((cc=getc(fin))!='\n')
  248.                                 ungetc(cc, fin);
  249.                         }
  250.                         break;
  251.                     }
  252.                 }
  253.                 MOCHAR(c);
  254.                 continue;
  255.             }
  256.         }
  257.  
  258.             /* time to do something */
  259.         if(Timeout == Tpause)
  260.         {
  261.  
  262.             Waitecho=FALSE;
  263.  
  264.                 /* dump buffer if full */
  265.             if(Xoffflg)
  266.             {
  267.                 dumprxbuff();
  268.                     /* allow term output to catch up */
  269.                 if(bufcdq != bufcq)
  270.                     continue;
  271.                     /* allow printer output to catch up */
  272.                 if(Pflag && bufpcdq != bufcq)
  273.                     continue;
  274.                 Xoffflg=FALSE;
  275.                 MOCHAR(xon);
  276.             }
  277. #ifdef CDO
  278.             if(CDO)
  279.             {
  280.                 pstat("Carrier Lost");
  281.                 return;
  282.             }
  283. #endif
  284.         }
  285.         else
  286.             ++Timeout;
  287.  
  288.             /* buffer overflow */
  289.         if (overrun)
  290.         {
  291.             lpstat("\007OVERRUN: DATA LOST");
  292.             overrun = 0;
  293.             return;
  294.         }
  295.  
  296.         if(--Txtimeout==0)
  297.             Txwait=FALSE;
  298.     }
  299.  
  300. } /* term */
  301.  
  302.  
  303. /****************************************************************************
  304. FUNCTION:
  305.     display the status information on entering term()
  306.  
  307. CALLING PARAMETERS:
  308.     none
  309. ===========================================================================*/
  310. sayterm()
  311. {
  312.     if(Tfile)
  313.         pstat("Sending '%s' %s", Tname, Txgo?"":"Stopped by XOFF");
  314.     else if(Rfile)
  315.         pstat("Term Receiving '%s'", Rname);
  316.     else
  317.         pstat("Term Function");
  318. } /* sayterm */
  319.  
  320.  
  321. /****************************************************************************
  322. FUNCTION:
  323.     open a capture file and set the removal pointer to get max goods
  324.     called from main menu with t [filename].
  325.  
  326. CALLING PARAMETERS:
  327.     char *name:
  328.         pointer to file name to capture text to.
  329. ===========================================================================*/
  330. opencapt(name)
  331. char *name;
  332. {
  333.         /* close any existing file */
  334.     dumprxbuff();
  335.     closerx(TRUE);
  336.     if(openrx(name)==ERROR)
  337.         return ERROR;
  338.     if(buffcdq<bufst)
  339.         buffcdq=bufst;
  340.     if(Wrapped)
  341.         buffcdq=bufcq+1;
  342.     if(buffcdq >= bufend)
  343.         buffcdq=bufst;
  344.     return OK;
  345. } /* opencapt */
  346.  
  347.  
  348. /****************************************************************************
  349. FUNCTION:
  350.     dump circular buffer to disk
  351.  
  352. CALLING PARAMETERS:
  353.     none
  354. ===========================================================================*/
  355. dumprxbuff()
  356. {
  357.     register c;
  358.  
  359.     Nfree=Bufsize;
  360.     if(!Rfile || buffcdq==NULL)
  361.         return OK;
  362.     while(buffcdq != bufcq)
  363.     {
  364.         c= *buffcdq++;
  365.         if(buffcdq >= bufend)
  366.             buffcdq=bufst;
  367.         switch(c &= 0177)
  368.         {
  369.         case 0:
  370.              continue;
  371.         case 0x1A:        /* ^Z */
  372.             if(Zeof)
  373.             {
  374.                 closerx(TRUE);
  375.                 return OK;
  376.             }
  377.             else
  378.                 break;
  379.         case 0x12:
  380.             if(Squelch)
  381.             {
  382.                 Dumping=TRUE;
  383.                 continue;
  384.             }
  385.             break;
  386.         case 0x14:
  387.             if(Squelch)
  388.             {
  389.                 Dumping=FALSE;
  390.                 continue;
  391.             }
  392.             break;
  393.         default:
  394.             break;
  395.         }
  396.         if(Dumping)
  397.             if(putc(c, fout)==ERROR)
  398.             {
  399.                 printf("\nDisk Full\n");
  400.                 closerx(FALSE);
  401.                 return ERROR;
  402.             }
  403.     }
  404.     return OK;
  405. } /* dumprxbuff */
  406.  
  407.  
  408. /****************************************************************************
  409. FUNCTION:
  410.     set buffer pointers back to start of data in buffer, or start of buffer
  411.     if the pointers have wrapped.  Entering term after a rewind will cause
  412.     re-display of all captured data in buffer.
  413.  
  414. CALLING PARAMETERS:
  415.     none
  416. ===========================================================================*/
  417. rewindcb()
  418. {
  419.     bufcdq=buffcdq=bufpcdq=Wrapped?bufcq+1:bufst;
  420. }
  421.  
  422. /****************************************************************************
  423. FUNCTION:
  424.     replot redisplays the buffer contents thru putcty allowing xoff
  425.     number will represent how many lines to go back first 
  426.  
  427. CALLING PARAMETERS:
  428.     number:
  429.         number of characters to re-display
  430. ===========================================================================*/
  431. replot(number)
  432. int number;
  433. {
  434.     char doexit;
  435.     char *reptr;
  436.     char c;
  437.     char *smark;
  438.     char *p;
  439.     int    count;
  440.     int n;
  441.  
  442.     doexit=FALSE;
  443.  
  444. fromtop:
  445.     smark=reptr=bufmark=Wrapped?bufcq+1:bufst;
  446.  
  447.     if(number)
  448.     {
  449.         reptr=bufcq;
  450.  
  451.     /* backup up number lines.  They will be displayed by nextline */
  452. backsome:
  453.         /* backing up is confusing unless screen is cleared first */
  454.     for (n=1; n<TLENGTH; n++)
  455.         CONOUT('\n');
  456.  
  457.         for(;;)
  458.         {
  459.             --reptr;
  460.  
  461.             /* adjust for pointer wrap */
  462.             if(reptr<bufst)
  463.             {
  464.                 if(Wrapped)
  465.                     reptr = bufend-1;
  466.                 else
  467.                 {
  468.                     reptr = bufst;
  469.                     break;
  470.                 }
  471.             }
  472.             /* hit begining of buffer */
  473.             if(reptr==bufcq)
  474.                 break;
  475.             /* test for line count */
  476.             if((*reptr&0177)=='\n' && --number<=0)
  477.                 break;
  478.         }
  479.         bufmark=reptr;
  480.     }
  481.  
  482. nextscreen:
  483.     count = TLENGTH - number;
  484.  
  485.     /* display count lines */
  486. nextline:
  487.     while(reptr != bufcq)
  488.     {
  489.         cfast= *reptr++ & 0177;
  490.         if(reptr >= bufend)
  491.             reptr=bufst;
  492.         if(c=putcty(cfast))
  493.             goto choose;
  494.         if (cfast=='\n' && --count<=0)
  495.             break;
  496.     }
  497.  
  498.     if (doexit)
  499.     {
  500.         sayterm();
  501.         return;
  502.     }
  503. #ifdef STATLINE
  504.     pstat("more ?");
  505. #else
  506.     printf("\rmore ?");
  507. #endif
  508.     c=getcty();
  509. #ifdef STATLINE
  510.     pstat("");
  511. #else
  512.     printf("\r       \r");
  513. #endif
  514.  
  515. choose:
  516. /* Treat Control chars and letters the same */
  517.     switch((c|0x60)&0x7f)
  518.     {
  519.     case 'x':
  520.         doexit = TRUE;
  521.         number = TLENGTH;
  522.         reptr = bufcq;
  523.         goto backsome;
  524.     case 'o':    /* /|0x60=o  search command */
  525.         putcty('/');
  526.         smark = bufmark; /* search from start of screen */
  527.         gets(Utility.ubuf);
  528.         uncaps(Utility.ubuf);
  529.         /* FALL THROUGH TO */
  530.     case 'n': /* find next */
  531.         if ((p = cisubstr(smark, Utility.ubuf)) && p<bufend)
  532.         {
  533.             smark = 1 + (bufmark = reptr = p);    /* +1 so n can work */
  534.             number = 1;
  535.             goto backsome;
  536.         } else
  537.             putcty(007);
  538.         /* FALL THROUGH TO */
  539.     case 'b': /* beginning of buffer */
  540.         number = 0;
  541.         goto fromtop;
  542.     case 'r':    /* control-r or r = previous page */
  543.     case 'h':    /* backspace */
  544.         number = TLENGTH-3;
  545.         reptr = bufmark;
  546.         goto backsome;
  547.     case 0x60:    /* space bar = next page */
  548.         number = 3;
  549.         bufmark = reptr;
  550.         goto nextscreen;
  551.     case 'p': /* previous line */
  552.         number = 1;
  553.         reptr = bufmark;
  554.         goto backsome;
  555.     case 'j':    /* linefeed */
  556.         bufmark = reptr;
  557.         count = 1;
  558.         goto nextline;
  559.     default:
  560.         return;
  561.     }
  562. } /* replot */
  563.  
  564.  
  565. /****************************************************************************
  566. FUNCTION:
  567.     moment waits a moment and returns FALSE, if no character keyboarded in
  568.     the meantime, otherwise returns TRUE.
  569.  
  570. CALLING PARAMETERS:
  571.     none
  572. ===========================================================================*/
  573. moment()
  574. {
  575.     sleep(3);
  576.     if (CIREADY)
  577.     {
  578.         getcty();
  579.         return TRUE;
  580.     }
  581.     return FALSE;
  582. } /* moment */
  583.  
  584.  
  585.  
  586. /****************************************************************************
  587. FUNCTION:
  588.     chat function.  Allow person to talk to operator at other end
  589.  
  590. CALLING PARAMETERS:
  591.     none
  592. ===========================================================================*/
  593. dochat()
  594. {
  595. #ifdef XMODEM
  596.     printf("Exit chat with ^Z\n");
  597. #endif
  598.     Chat=Ctlview=Hdx=Echo=TRUE;
  599.     term();
  600. } /* dochat */
  601.  
  602.  
  603.  
  604. /****************************************************************************
  605. FUNCTION:
  606.     Handle keyboard input. Returns TRUE iff caller should return to
  607.     command mode.
  608.  
  609. CALLING PARAMETERS:
  610.     cf:
  611.         char from keyboard.  for IBM PC, keycode is in high byte, ascii
  612.         char is in low byte.
  613. ===========================================================================*/
  614. doykbd(cf)
  615. int cf;
  616. {
  617.     switch (cf & 0x7F)
  618.     {
  619.         case ENQ:
  620.             if (moment())    /* ^E exits term */
  621.                 break;
  622.             pstat(" ");
  623.             return TRUE;
  624.         case 0x12:            /* ^r */
  625.             if (moment())
  626.                 break;
  627.             replot(TLENGTH-1);
  628.             return;
  629.         case BRKKEY:        /* BRK KEY sends break */
  630.             if (moment())
  631.                 break;
  632.             sendbrk();
  633.             while (CIREADY)
  634.                 getcty();    /* discard garbage */
  635.             return FALSE;
  636.         case '\r':
  637.             if(Hdx)
  638.                 printf("\n");
  639.             if(Chat)
  640.                 sendbyte('\n');
  641.             break;
  642.         default:
  643.             if (cf==xon)
  644.             {
  645.                 if(Tfile && !Txgo)
  646.                 {
  647.                     Txgo=TRUE;
  648.                     sayterm();
  649.                 }
  650.             }
  651.             else if (cf==xoff)
  652.             {
  653.                 if(Tfile && Txgo)
  654.                 {
  655.                     Txgo=FALSE;
  656.                     sayterm();
  657.                 }
  658.             }
  659.     }
  660.  
  661. #ifdef IBMPC
  662.         /* extended key codes for IBM PC. Low order byte is 0 */
  663.     if (!(cf & 0xFF))
  664.         switch (cf)
  665.         {
  666.                 /* del key */
  667.             case 0x5300:
  668.                 cf = 0x7F;
  669.                 break;
  670.             default:
  671.                 return FALSE;
  672.         }
  673. #endif
  674.  
  675.         /* send char to modem if not special key */
  676.     MOCHAR(cf & 0x7f);
  677.     if(Hdx)
  678.         CONOUT(cf);
  679.     return FALSE;
  680. }/* doykbd */
  681.